package com.usf.jprovider.object;

import java.util.ArrayList;
import java.util.List;

import com.usf.jprovider.constants.Constants;
import com.usf.jprovider.exception.FieldNotFoundException;
import com.usf.jprovider.object.type.JString;
import com.usf.jprovider.object.type.JType;

public class JObjectNode{
	
	protected String name;
	protected JType<?> value;
	
	protected boolean changed;
	protected int entryIndex;
	protected int valueIndex;

	protected JObject root;
	protected JObjectNode parent;
	protected List<JObjectNode> childs;
	
	protected JObjectNode() {
		this.childs = new ArrayList<JObjectNode>();
		this.name = "";
		this.value = new JString("");
		this.valueIndex = this.entryIndex = 0;
		this.changed = false;
	}
	
	protected JObjectNode(String name, JObject root){
		this();
		this.name = name;
		this.root = root;
		this.value = new JString("");
		this.valueIndex = this.entryIndex = 0;
		this.changed = false;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public JType<?>  getValue() {
		return value;
	}
	public void setValue(JType<?> value) {
		this.value = value;
	}
	public void changeValue(JType<?> value){
		this.value = value;
		this.changed = true;
	}
	public void changeValue(String value) throws Exception {
		this.value.set(value);
		this.changed = true;
	}
	
	public boolean isChanged() {
		return changed;
	}
	public void setChanged(boolean cahnged) {
		this.changed = cahnged;
	}

	public int getValueIndex() {
		return valueIndex;
	}
	public void setValueIndex(int index) {
		this.valueIndex = index;
	}
	public int getEntryIndex() {
		return entryIndex;
	}
	public void setEntryIndex(int entryIndex) {
		this.entryIndex = entryIndex;
	}

	public JObject getRoot() {
		return root;
	}
	public void setRoot(JObject root) {
		this.root = root;
	}
	public JObjectNode getParent() {
		return parent;
	}
	public void setParent(JObjectNode parent) {
		this.parent = parent;
	}
		
	public boolean hasChilds(){
		return childs.size() > 0;
	}
	public boolean isRoot(){
		return parent == null;
	}
	
	public JObjectNode create(String name){
		return new JObjectNode(name, root);
	}
	
	public void addChild(JObjectNode node){
		node.setParent(this);
		childs.add(node);
	}
	public void removeChild(JObjectNode node){
		childs.remove(node);
	}
	public JObjectNode firstChild(){
		return childs.get(0);
	}
	public JObjectNode lastChild(){
		return childs.get(childs.size()-1);
	}
	
	public JObjectNode child(String name) throws FieldNotFoundException {
		int i = 0;
		while(i < childs.size() && !childs.get(i).getName().equals(name)) i++;
		if(i < childs.size()) return childs.get(i);
		throw new FieldNotFoundException(name);
	}	
	public JObjectNode[] childs(){
		JObjectNode[] tab = new JObjectNode[childs.size()];
		return childs.toArray(tab);
	}
	public JObjectNode childPath(String path) throws FieldNotFoundException {
		String[] values = path.split(Constants.MEMBER_SEPARATOR_SPLIT);
		JObjectNode node = this;
		for(int i=0; i<values.length; i++)
			node = node.child(values[i]);
		return node;
	}	
	
	public String path(){
		StringBuilder path = new StringBuilder(name);
		JObjectNode node = parent;
		while(!node.isRoot()) {
			path.insert(0, node.getName() + Constants.MEMBER_PATH_SEPARATOR);
			node = node.getParent();
		}
		return path.toString();
	}
		
	@Override
	public String toString() {
		return "JObjectNode [name=" + name + ", value=" + value
				+ ", valueIndex=" + valueIndex + ", EntryIndex="
				+ entryIndex + "]";
	}
}
